package com.atgouwu.scmall.seckill.service.impl;

import com.atgouwu.scmall.seckill.entity.OrderEntity;
import com.atgouwu.scmall.seckill.entity.OrderItemEntity;
import com.atgouwu.scmall.seckill.service.RabbitMqService;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;

@Service
@RabbitListener(queues = {"test.release.test.queue"}) //**(实现类上或方法上)监听的队列名,同一个消息只能被一个客户端收到,只有消息被消费且方法运行后,才能接收到下一条消息
public class RabbitMqServiceImpl implements RabbitMqService {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * RabbitMQ发送消息: 可发送多个
     */
    @Override
    public String rabbitMq(Long id) {
        OrderEntity order = new OrderEntity(); //准备数据
        order.setId(id);
        //发送消息: 交换机名称(同绑定),路由键(同绑定),任意类型消息(对象需序列化,或json配置类),消息唯一id
        rabbitTemplate.convertAndSend("test-event-exchange", "test.release.test", order, new CorrelationData(UUID.randomUUID().toString()));
        //定时任务: 发送给死信队列,过期后会发送给普通队列,普通队列监听,执行定时任务
        rabbitTemplate.convertAndSend("test-event-exchange", "test.create.test", order, new CorrelationData(UUID.randomUUID().toString()));
        OrderItemEntity orderItemEntity = new OrderItemEntity(); //准备数据
        orderItemEntity.setOrderId(id);
        //发送消息: 交换机名称(同绑定),路由键(同绑定),任意类型消息(对象需序列化,或json配置类),消息唯一id
        rabbitTemplate.convertAndSend("test-event-exchange", "test.release.test", orderItemEntity, new CorrelationData(UUID.randomUUID().toString()));
        return "rabbitMq发送成功";
    }

    /**
     * 监听(接收消息): 根据实体类型接收
     */
    @RabbitHandler //**(方法上)处理消息
    public void recieveMessage(Message message, OrderEntity order, Channel channel) { //原生消息,用对象接收(发的对象),通道
        byte[] body = message.getBody(); //消息体
        MessageProperties messageProperties = message.getMessageProperties(); //消息头
        //System.out.println("消息:" + message + ",类型:" + message.getClass() + ",消息体:" + body);
        try {
            Long deliveryTag = messageProperties.getDeliveryTag();
            channel.basicAck(deliveryTag, false); //消费者-手动签收: 标签(通道内按顺序自增),不批量签收(默认自动签收,签收后从队列移除)
            //channel.basicNack(deliveryTag, false, false); //拒收: 标签,不批量拒收(true以前全部被拒),不重新入队(丢弃,true重新入队)
            //channel.basicReject(deliveryTag, false); //拒收: 标签,不重新入队
        } catch (Exception e) {
            //网络中断
            e.printStackTrace();
        }
    }

    /**
     * 监听(接收消息): 根据实体类型接收
     *               方法重载:接收不同类型消息(不同实体类)
     */
    @RabbitHandler //**(方法上)处理消息
    public void recieveMessages(Message message, OrderItemEntity orderItemEntity, Channel channel) { //原生消息,用对象接收(发的对象),通道
        byte[] body = message.getBody(); //消息体
        MessageProperties messageProperties = message.getMessageProperties(); //消息头
        //System.out.println("消息:" + message + ",类型:" + message.getClass() + ",消息体:" + body);
        try {
            Long deliveryTag = messageProperties.getDeliveryTag();
            //channel.basicAck(deliveryTag, false); //消费者-手动签收:标签(通道内按顺序自增),不批量签收。默认自动签收,签收后从队列移除
            channel.basicNack(deliveryTag, false, false); //拒收:标签,不批量拒收(true以前全部被拒),不重新入队(丢弃,true重新入队)
            //channel.basicReject(deliveryTag, false); //拒收:标签,不重新入队
        } catch (Exception e) {
            //网络中断
            e.printStackTrace();
        }
    }

}
